﻿using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Linq;
using System.Text;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using ServiceAuthJwt.Model;
using ServiceAuthJwt.Web;
using ServiceAuthJwt.Cache.Redis;
using UtilsCache;
using Newtonsoft.Json;

namespace ServiceAuthJwt.Auth
{
    public class TokenAuthenticationService : IAuthenticateService
    {
        private  TokenManagement _tokenManagement = new TokenManagement();
        public TokenAuthenticationService()
        {
            _tokenManagement.Issuer = UtilAppsettingCache.getSetting("TokenManagement:Issuer");
            _tokenManagement.AccessExpiration = int.Parse(UtilAppsettingCache.getSetting("TokenManagement:AccessExpiration"));
            _tokenManagement.Audience = UtilAppsettingCache.getSetting("TokenManagement:Audience");
            _tokenManagement.Secret = UtilAppsettingCache.getSetting("TokenManagement:Secret");
            _tokenManagement.RefreshExpiration = int.Parse(UtilAppsettingCache.getSetting("TokenManagement:RefreshExpiration"));
        }

        /// <summary>
        /// 获取 Token
        /// </summary>
        /// <param name="request"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool IsAuthenticated(DTOLoginRequest request,int type, out string token)
        {
            token = string.Empty;
           // if (request.Username != "admin" || request.Password != "123456")
          //      return false;
           // request.UserId = 1;

            var claims = new[]
            {
                new Claim(ClaimTypes.Name,request.Username),
                new Claim(ClaimTypes.NameIdentifier,request.UserId.ToString())
            };
            int expMin = 0;
            if(type==0)
            {
                //token
                expMin = _tokenManagement.AccessExpiration;;
            }
            else
            {//RefreshToken
                expMin = _tokenManagement.RefreshExpiration ;
            }
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenManagement.Secret));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var jwtToken = new JwtSecurityToken(
                _tokenManagement.Issuer,
                _tokenManagement.Audience, claims,
                expires: DateTime.Now.AddMinutes(expMin),//(_tokenManagement.AccessExpiration),
                signingCredentials: credentials
                ); 
            token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
            if (type == 0)
            {//Token
                UtilMemoryCacheHelper.set(RedisPrefix.User_Login_Token_Key.GetKey(request.UserId), token, expMin*60 );
            }
            

            UtilMemoryCacheHelper.set("DTOLoginRequest"+ request.UserId, JsonConvert.SerializeObject(request), expMin * 60);

            return true;
        }

       
        

        /// <summary>
        /// Token 刷新
        /// </summary>
        /// <param name="claims"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool IsAuthenticated(IEnumerable<Claim> claims, out string token)
        {
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenManagement.Secret));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var jwtToken = new JwtSecurityToken(
                _tokenManagement.Issuer,
                _tokenManagement.Audience, claims,
                expires: DateTime.Now.AddMinutes(_tokenManagement.AccessExpiration),//(_tokenManagement.AccessExpiration),
                signingCredentials: credentials
                );

            token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
            UtilMemoryCacheHelper.set(RedisPrefix.User_Login_Token_Key.GetKey(claims.GetUserId()), token, _tokenManagement.RefreshExpiration * 60);
            return true;
        }


        public Dictionary<string, string> createToken(DTOLoginRequest request)
        {
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
            if (IsAuthenticated(request, 0, out string outToken))
            {
               // UtilMemoryCacheHelper.set("token" + request.UserId, outToken, 120);
                keyValuePairs.Add("token", "Bearer " + outToken);
            }

            if (IsAuthenticated(request, 1, out string outRefreshToken))
            {
                UtilMemoryCacheHelper.set("refreshToken", outRefreshToken, _tokenManagement.RefreshExpiration * 60);
                keyValuePairs.Add("refreshToken" , outRefreshToken);
            }
            return keyValuePairs;
        }
    }
}
